package com.jubaozan.framework.sentinel.stat.traffic;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantLock;
import lombok.Data;
import lombok.RequiredArgsConstructor;

import lombok.extern.slf4j.Slf4j;

/**
 * @author jiangjinwu
 * @version 1.0
 * @since 2025/7/23 18:50
 */

@Slf4j

public class TrafficLogSecondCache {

    private static final ReentrantLock LOCK = new ReentrantLock();

    // 缓存结构：key=数据的秒级时间戳+IP+资源（确保数据归属正确的秒）
    private static final Map<String, TrafficLog> CACHE = new ConcurrentHashMap<>();

    /**
     * 添加流量记录，使用请求实际发生的时间戳（而非当前时间）
     * @param requestTime 请求发生的时间戳（毫秒，如preHandle中记录的startTime）
     */
    public static void addTrafficLog(String resource, String app, String ip, double rt,
        boolean isSuccess, long requestTime) {
        // 1. 基于请求实际发生时间计算秒级时间戳（而非当前时间）
        long secondTimestamp = requestTime / 1000 * 1000; // 取请求发生时的秒级时间
        String cacheKey = secondTimestamp + "_" + ip + "_" + resource;

        // 2. 聚合数据（使用请求发生时间作为数据时间戳）
        CACHE.compute(cacheKey, (k, log) -> {
            if (log == null) {
                log = new TrafficLog();
                log.setTimestamp(new Date(secondTimestamp)); // 数据时间戳=请求发生的秒
                log.setIp(ip);
                log.setApp(app);
                log.setResource(resource);
                log.setTotalCount(1);
                log.setTotalRt(rt);
                log.setSuccessCount(isSuccess ? 1 : 0);
                log.setExceptionCount(isSuccess ? 0 : 1);
            } else {
                log.setTotalCount(log.getTotalCount() + 1);
                log.setTotalRt(log.getTotalRt() + rt);
                if (isSuccess) {
                    log.setSuccessCount(log.getSuccessCount() + 1);
                } else {
                    log.setExceptionCount(log.getExceptionCount() + 1);
                }
            }
            return log;
        });
    }

    /**
     * 获取并清空缓存的所有记录（供定时任务调用）
     */
    public static List<TrafficLog> takeAllAndClear() {
        try {
            LOCK.lock();
            List<TrafficLog> logs = new ArrayList<>(CACHE.values());
            CACHE.clear();
            return logs;
        } finally {
            LOCK.unlock();
        }
    }

    // 正常流量记录实体
    @Data
    public static class TrafficLog {
        private Date timestamp; // 秒级时间戳
        private String ip; // 实例IP
        private String app; // 应用名
        private String resource; // 资源名
        private int totalCount; // 总访问次数
        private int successCount; // 成功次数
        private int exceptionCount; // 异常次数
        private double totalRt; // 总响应时间（毫秒）

    }
}
